package com.oj.facade;

import com.oj.api.auth.IAuthFacade;
import com.oj.api.auth.domain.AccountInfo;
import com.oj.api.auth.service.IAccountService;
import com.oj.api.core.ICoreFacade;
import com.oj.api.core.domain.JudgeInfo;
import com.oj.api.core.domain.ProblemInfo;
import com.oj.api.core.domain.ProblemSetCategoryInfo;
import com.oj.api.core.domain.ProblemSetInfo;
import com.oj.api.core.service.IJudgeService;
import com.oj.api.core.service.IProblemSetCategoryService;
import com.oj.common.IResourceLayer;
import com.oj.common.JsonResponse;
import com.oj.common.Response;
import com.oj.common.SystemTool;
import com.oj.common.util.BreezeeUtils;
import com.oj.common.util.UZipFile;
import com.oj.netflix.FeignClientException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;


/**
 * 核心资源实现
 * <p>
 * Created by ZhouBing on 2018/5/4.
 */
@RestController
public class CoreFacade implements ICoreFacade, IResourceLayer {

   @Autowired
   private IProblemSetCategoryService problemSetCategoryService;
   @Autowired
   private IJudgeService judgeService;


    @GetMapping("/core/test")
    @Override
    public Response testSave() {

        ProblemSetInfo problemSetInfo1 = new ProblemSetInfo();
        problemSetInfo1.setName("基础编程题目集1");
        problemSetInfo1.setCode("p001");

        ProblemSetInfo problemSetInfo2 = new ProblemSetInfo();
        problemSetInfo2.setName("基础编程题目集2");
        problemSetInfo2.setCode("p002");


        ProblemSetCategoryInfo problemSetCategoryInfo  = new ProblemSetCategoryInfo();
        problemSetCategoryInfo.setCode("001");
        problemSetCategoryInfo.setName("默认");

        List<ProblemSetInfo> problemSetInfoList = new ArrayList<>();
        problemSetInfoList.add(problemSetInfo1);
        problemSetInfoList.add(problemSetInfo2);


        problemSetCategoryInfo.setProblemSets(problemSetInfoList);

        problemSetCategoryInfo.getProperties().put("save",true);

        problemSetCategoryService.saveInfo(problemSetCategoryInfo);

        return null;
    }

    @PostMapping("/core/saveProblem")
    @Override
    public Response saveProblem(@RequestBody ProblemInfo problemInfo) {
        return JsonResponse.buildSingle(problemSetCategoryService.saveProblemInfo(problemInfo));
    }

    @PostMapping("/core/findProblemInfos")
    @Override
    public Response findProblemInfos(@RequestBody ProblemInfo problemInfo) {
        return JsonResponse.build(problemSetCategoryService.findPageProblemInfos(problemInfo));
    }

    @PostMapping("/core/findProblemSetCategory")
    @Override
    public Response findProblemSetCategory(@RequestBody ProblemSetCategoryInfo problemSetCategoryInfo) {
        return JsonResponse.build(problemSetCategoryService.listInfos(problemSetCategoryInfo));
    }


    @PostMapping("/core/upload")
    @ResponseBody
    public Response handleFileUpload(@RequestParam("file") MultipartFile file){

        //todo 不能写在这里 应该写到判题模块下
        if (!file.isEmpty()) {
            String targetUid = null;
            List<String> list = null;
            String date = null;
            try {
                /*
                 * 这段代码执行完毕之后，图片上传到了工程的跟路径； 大家自己扩散下思维，如果我们想把图片上传到
                 * d:/files大家是否能实现呢？ 等等;
                 * 这里只是简单一个例子,请自行参考，融入到实际中可能需要大家自己做一些思考，比如： 1、文件路径； 2、文件名；
                 * 3、文件格式; 4、文件大小的限制;
                 */
                System.out.println(file.getOriginalFilename());
                File dir = new File("C:\\ojData\\");
                if(!dir.exists()){
                    dir.mkdirs();
                }
                String zipPath = "C:\\ojData\\"+file.getOriginalFilename();
                BufferedOutputStream out = new BufferedOutputStream(
                        new FileOutputStream(new File(zipPath)));
                System.out.println(file.getName());
                out.write(file.getBytes());
                out.flush();
                out.close();


                targetUid = SystemTool.uuid().replaceAll("-","");

                /**
                  * 解压文件
                  */
                File zipFile = new File(zipPath);
                String tarPath = "C:/ojData/"+targetUid+"/";
                File tarDir = new File(tarPath);
                if(!dir.exists()){
                    dir.mkdirs();
                }
                UZipFile.unZipFiles(zipFile, tarPath);
                File[] files = tarDir.listFiles();
                List<String> names = new ArrayList<>();
                //1.判断是输入文件、输出文件是否一一对应
                for (File f :files) {
                    names.add(f.getName());
                }
                for (String a:names) {
                    if(a.endsWith(".in")){
                        if(!names.contains(a.substring(0,a.length()-3)+".out")){
                            return JsonResponse.error("缺少文件:"+a.substring(0,a.length()-3)+".out");
                        }
                    }
                    if(a.endsWith(".out")){
                        if(!names.contains(a.substring(0,a.length()-4)+".in")){
                            return JsonResponse.error("缺少文件:"+a.substring(0,a.length()-4)+".in");
                        }
                    }
                }
                if(!names.contains("scores.txt")){
                    return JsonResponse.error("缺少文件:scores.txt");
                }

                BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(tarPath+"scores.txt"), "UTF-8"));
                list = new ArrayList<String>();
                String score = null;
                while ((score=br.readLine())!=null){
                    String testCode = score.split(" ")[0];
                    File testFile = new File((tarPath+testCode+".in").replaceAll("\uFEFF", ""));
                    list.add(score.replaceAll(" ","_")+"_"+ BreezeeUtils.DATE_FORMAT_LONG.format(new Date(testFile.lastModified())));
                }
                for (String a:list) {
                    System.out.println("值为:"+a);
                }
            } catch (IOException e) {
                e.printStackTrace();
                return JsonResponse.error("上传失败," + e.getMessage());
            }
            return JsonResponse.build(list).buildMsg("上传成功@"+targetUid);
        } else {
            return JsonResponse.error("上传失败，因为文件是空的.");
        }
    }

    @GetMapping("/core/findTestData/{code}")
    public Response findTestData(@PathVariable("code") String code){

        String tarPath = "C:/ojData/"+code+"/";
        BufferedReader br = null;

        /*File file = new File(tarPath+"0.in");

        if(!file.exists()){
            System.out.println("文件不存在");
        }
        Calendar cal = Calendar.getInstance();
        long time = file.lastModified();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        cal.setTimeInMillis(time);
        System.out.println("修改时间[2] " + formatter.format(cal.getTime()));*/

        try {
            br = new BufferedReader(new FileReader(new File(tarPath+"scores.txt")));
            List list = new ArrayList<String>();
            String score = null;
            while ((score=br.readLine())!=null){
                String testCode = score.split(" ")[0];
                File testFile = new File((tarPath+testCode+".in").replaceAll("\uFEFF", ""));
                list.add(score.replaceAll(" ","_")+"_"+ BreezeeUtils.DATE_FORMAT_LONG.format(new Date(testFile.lastModified())));
            }
            return JsonResponse.build(list);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(br!=null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }


    @PostMapping("/core/findProblemSet")
    @Override
    public Response findProblemSet(@RequestBody ProblemSetInfo problemSetInfo) {
        return JsonResponse.buildSingle(problemSetCategoryService.findProblemSetInfo(problemSetInfo));
    }

    @PostMapping("/core/findProblemSetInfos")
    @Override
    public Response findProblemSetInfos(@RequestBody ProblemSetInfo problemSetInfo) {

        String role = null;
        if(problemSetInfo.getProperties().get("role")!=null){
            role = problemSetInfo.getProperties().get("role").toString();
            problemSetInfo.getProperties().remove("role");
        }

        List<ProblemSetInfo> result = new ArrayList<>();
        //除了考试 都会查找公共的题目集
        if(!(problemSetInfo.getProperties().get("exam")!=null&&problemSetInfo.getProperties().get("exam").equals(true))){
            ProblemSetInfo info  = new ProblemSetInfo();
            info.addProperties("open",1);
            result.addAll(problemSetCategoryService.findProblemSetInfos(info));
        }
        //非游客查询非公共
        if(problemSetInfo.getProperties().get("visitor")==null){
            if("student".equals(role)&&problemSetInfo.getProperties().get("exam")==null){
                problemSetInfo.addProperties("type",1);
            }
            problemSetInfo.addProperties("open",0);
            result.addAll(problemSetCategoryService.findProblemSetInfos(problemSetInfo));
        }
        return JsonResponse.build(result);
    }

    @PostMapping("/core/findProblemSetList")
    @Override
    public Response findProblemSetList(@RequestBody ProblemSetInfo problemSetInfo) {
        return JsonResponse.build(problemSetCategoryService.findProblemSetInfos(problemSetInfo));
    }

    @PostMapping("/core/addProblemsToSet")
    @Override
    public Response addProblemsToSet(@RequestBody ProblemSetInfo problemSetInfo) {
        return JsonResponse.buildSingle(problemSetCategoryService.addProblemsToSet(problemSetInfo));
    }

    @GetMapping("/core/findProblem/{code}")
    @Override
    public Response findProblem(@PathVariable("code") String code) {
        return JsonResponse.buildSingle(problemSetCategoryService.findProblemInfo(code));
    }

    @PostMapping("/core/saveJudgeInfo")
    @Override
    public Response saveJudgeInfo(@RequestBody JudgeInfo judgeInfo) {


        ProblemSetInfo setInfo = new ProblemSetInfo();
        setInfo.setCode(judgeInfo.getProblemSetCode());
        setInfo = problemSetCategoryService.findProblemSetInfo(setInfo);

        /*考试情况下 判断是否在考试时间之内*/
        Long curTime = System.currentTimeMillis();
        if(setInfo.getType().equals(0)&&(setInfo.getStartTime().getTime()>curTime||setInfo.getEndTime().getTime()<curTime)){
            return JsonResponse.error("考试结束");
        }
        judgeInfo = judgeService.judge(judgeInfo);
        return JsonResponse.buildSingle(judgeInfo);
    }

    @GetMapping("/core/findJudgeInfoByCode/{code}")
    @Override
    public Response findJudgeInfoByCode(@PathVariable("code") String code) {
        return JsonResponse.buildSingle(judgeService.findInfoById(code));
    }
    @PostMapping("/core/createCategory")
    @Override
    public Response createCategory(@RequestBody ProblemSetCategoryInfo problemSetCategoryInfo) {
        problemSetCategoryInfo.setCode(SystemTool.getCode());
        problemSetCategoryInfo.getProperties().put("save",true);

        problemSetCategoryService.saveInfo(problemSetCategoryInfo);
        return JsonResponse.buildSingle("success");
    }

    @PostMapping("/core/createSet")
    @Override
    public Response createSet(@RequestBody ProblemSetCategoryInfo problemSetCategoryInfo) {
        return JsonResponse.buildSingle(problemSetCategoryService.createSet(problemSetCategoryInfo));
    }

    @PostMapping("/core/updateSet")
    @Override
    public Response updateSet(@RequestBody ProblemSetInfo problemSetInfo) {
        return JsonResponse.buildSingle(problemSetCategoryService.updateSet(problemSetInfo));
    }

    @GetMapping("/core/problemSet/{code}")
    @Override
    public Response getSet(@PathVariable("code") String code) {
        return JsonResponse.buildSingle(problemSetCategoryService.getProblemSet(code));
    }

    @PostMapping("/core/findPageJudgeInfos")
    @Override
    public Response findPageJudgeInfos(@RequestBody JudgeInfo judgeInfo) {
        try {
            return JsonResponse.build(judgeService.pageInfos(judgeInfo));
        } catch (Exception e) {
            return JsonResponse.error(FeignClientException.populateMsg(e));
        }
    }

    @PostMapping("/core/findRankOfProblemSet")
    @Override
    public Response findRankOfProblemSet(@RequestBody JudgeInfo judgeInfo) {
        try {
            return JsonResponse.build(judgeService.findRankOfProblemSet(judgeInfo));
        } catch (Exception e) {
            return JsonResponse.error(FeignClientException.populateMsg(e));
        }
    }
}
